<template>
  <div :class="{[prefixCls+'-date-picker-input']:true,'date-picker-clear':value&&showClear}"> 
    <eminput 
      :placeholder="placeholder"
      :class="{'disabled':disabled}"
       ref="input"
      :value="showValue||value"
      :readonly="readonly"
      :disabled="disabled"
      :clear="showClear&&!disabled"
       @input="_input"
       @blur="_blur"
      >
    
    </eminput>
    <!-- <i class="icon-date" v-if="!disabled"></i>  -->
  </div>
</template>
<script>
import Vue from "vue"
import eminput  from '../input/index.vue'
import dom from '../mixins/dom'
const prefixCls="em"
import emitter from '../mixins/emitter'
import DatePicker from './datepicker'

const Picker = Vue.extend(DatePicker)
export default {
  name: `${prefixCls}DatePicker`,
  mixins: [dom,emitter],
  data() {
    return {
      prefixCls: prefixCls,
      component: '', // 挂载的组件
      offset: {}, // 当前input位置坐标
      status: false, // 防止多次挂裁
      showValue: '' // 显示在输入框的值
    }
  },
  watch: {
    value() {
      this._getShowValue()
    }
  },
  props: {
    value: [Number, String, Date],
    placeholder: String,
    showClear: {// 显示清空
      type: Boolean,
      default: true
    },
    disabledDate: {
      type: Function,
      default: function () {
        return false
      }
    },
    disabled: {
      type: Boolean,
      default: false
    },
    type: {
      type: String,
      default: 'date',
      validator: function (value) {
        // 下拉面板类型 四种类型，年/年月/年月日/年月日时分秒
        return ['year', 'month', 'date', 'datetime'].indexOf(value) !== -1
      }
    },
    format: String, // 显示于输入框的值的格式化
    valueFormat: String, // 实际值，即v-model
    innerHTML: Function,
    appendToBody: {
      // 将日期面板插入到body中
      type: Boolean,
      default: false
    },
    downStyle: Object, // 下拉面板样式
    readonly: { // 日期输入框只读  input 本身就带有只读属性
      type: Boolean,
      default: false
    }
  },
  components: {eminput},
  methods: {
    _getShowValue(date) {      //type 类型改变呼出 时间框类型改变 选中时间类型格式化
        // 当value变化时，返回指定的输出格式
      let dateValue = date || this.value
      if (!dateValue) {
        return
      }
      let type = ''
      switch (this.type) {
        case 'year':
          type = 'y'
          break
        case 'month':
          type = 'y-MM'
          break
        case 'date':
          type = 'y-MM-dd'
          break
        case 'datetime':
          type = 'y-MM-dd hh:mm:ss'
          break
      }
      if (this.format) {
        // 指定了显示的格式时，按指定的返回
        type = this.format
      }
      this.showValue = this._parseDate(dateValue, type)
      // 更新v-model
      const vModel = this._parseDate(dateValue, this.valueFormat || type)
      this._emit(vModel)
    },
    // 格式化时间
    _parseDate(date, formatType) {
      let dateTime = new Date(date)
      if (dateTime.toString() === 'Invalid Date') {
        // 日期不合法
        dateTime = ''
        throw new Error('日期不合法')
        // return date
      }
      if (formatType === 'timestamp') {
        return dateTime.getTime() // 时间戳直接返回
      }
      const m = dateTime.getMonth() + 1
      const d = dateTime.getDate()
      const h = dateTime.getHours()
      const mi = dateTime.getMinutes()
      const s = dateTime.getSeconds()
      const formatObj = {
        y: dateTime.getFullYear(),
        M: m,
        MM: m > 9 ? m : '0' + m,
        d: d,
        dd: d > 9 ? d : '0' + d,
        h: h,
        hh: h > 9 ? h : '0' + h,
        m: mi,
        mm: mi > 9 ? mi : '0' + mi,
        s: s,
        ss: s > 9 ? s : '0' + s,
        w: dateTime.getDay()
      }
      return formatType.replace(/(y|MM|M|dd|d|hh|h|mm|m|ss|s|w)/g, result => {
        let value = formatObj[result]
        if (result === 'w') return ['日', '一', '二', '三', '四', '五', '六'][value]
        return value
      })
    },
    _emit(date) {
      this.$emit('input', date)// 返回父组件更新
      // 通知表单组件
      // this.dispatch('formItem', `${prefixCls}.form.change`, [date, ''])
      this.$emit('change', date)
    },
    _open(e) {
      //组件展开时 出发此函数
      // 判断当前点击元素在组件里即展开，即属于组件子节点，不在关闭
      if (this.$el.contains(e.target) && !this.disabled && !this.status) {

        this.offset = this.getOffset(this.$refs.input.$el)


        if (!this.appendToBody) {
          // 将插入位置改为0
          this.offset.left = 0
          this.offset.top = 0
          this.offset.height=0  
        }
        const props = {
          downStyle: this.downStyle,
          offset: this.offset,
          value: this.value,
          input: (time) => {
            this._getShowValue(time)
            this.status = false
            // 这里更新下value
          },

          disabledDate: (time) => { // 不能选的日期
            return this.disabledDate && this.disabledDate(time)
          },
          type: this.type,
          innerHTML: (time) => {
            return this.innerHTML && this.innerHTML(time)
          }
        }
        
        //深拷贝
        const propsData = Object.assign({}, props)
        //实例化 date-picker组件对象挂载数学
        this.component = new Picker({propsData}).$mount()
        if (this.appendToBody) {
          document.body.appendChild(this.component.$el)
        } else {
          this.$el.appendChild(this.component.$el)
        }
        this.status = true
      } else {              //否则就关闭这个组件
        if (this.component) {
          this.component.close()
          this.status = false
        }
      }
    },

    _input(val) {
      // readonly=false时，用户输入事件。清空事件

      this.showValue = val
      if (val === '') {
        this._emit('')
      }
    },
    // 当只读模式为false，有失焦事件，对日期进行检验
    _blur(e) {
      // console.log('ok')
      // const value = e.target.value
      // if (!value) {
      //   return
      // }
      // let dateTime = new Date(value.toString())
      // if (dateTime.toString() === 'Invalid Date') {
      //   // 日期不合法
      //   dateTime = ''
      // }
      // this._emit(dateTime) 
    }
  },
  computed: {},
  mounted() {   //当组件生成完毕时挂载click事件和函数
    document.addEventListener('click', this._open)
    this._getShowValue()
  },
  beforeDestroy() {
    document.removeEventListener('click', this._open)
  },
  destroyed() {
    // if appendToBody is true, remove DOM node after destroy
    if (this.$el && this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el)
    }
  },
  filters: {}
}
</script>